//InvokeMethodTest.java
package com.ylaihui.getallstruct;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class InvokeMethodTest {
    @Test
    public void test() throws Exception {

        ClassLoader classLoader = InvokeMethodTest.class.getClassLoader();
        Class<?> clazz = classLoader.loadClass("com.ylaihui.getallstruct.Person");

        Person p = (Person) clazz.newInstance();

        //1.获取指定的某个方法
        //getDeclaredMethod():参数1 ：指明获取的方法的名称  参数2：指明获取的方法的形参列表
        Method show = clazz.getDeclaredMethod("show", String.class);

        //2.保证当前方法是可访问的
        show.setAccessible(true);

        //3. 调用方法的invoke():参数1：方法的调用者  参数2：给方法形参赋值的实参
        //invoke()的返回值即为对应类中调用的方法的返回值。
        Object returnval = show.invoke(p, "CHINA");
        System.out.println(returnval);

        // 调用静态方法，静态方法不属于任何对象
        Method showdesc = clazz.getDeclaredMethod("showDesc");

        showdesc.setAccessible(true);

        //以下两种调用方法 的形式都可以
        //Object invoke = showdesc.invoke(null);
        Object invoke = showdesc.invoke(Person.class);
        System.out.println(invoke);  // 方法没有返回值，返回null
    }

    //如何调用运行时类中的指定的构造器
    //用的比较少，一般都使用 空参 的构造器new对象 Person.class.newInstance()
    // 反射一般是用于比较通用的写法， 一般都使用空参的构造器，然后get set赋值和获取属性值
    @Test
    public void test1() throws Exception {
        Class clazz = Person.class;

        //private Person(String name)
        //1.获取指定的构造器
        //getDeclaredConstructor():参数：指明构造器的参数列表
        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //2.保证此构造器是可访问的
        constructor.setAccessible(true);

        //3.调用此构造器创建运行时类的对象
        Person per = (Person) constructor.newInstance("Tom");
        System.out.println(per);
    }
}
